/*
 *所有关于bas_label类的业务代码应在此处编写
*可使用repository.调用常用方法，获取EF/Dapper等信息
*如果需要事务请使用repository.DbContextBeginTransaction
*也可使用DBServerProvider.手动获取数据库相关信息
*用户信息、权限、角色等使用UserContext.Current操作
*bas_labelService对增、删、改查、导入、导出、审核业务代码扩展参照ServiceFunFilter
*/
using DGZImp.Core.BaseProvider;
using DGZImp.Core.Extensions.AutofacManager;
using DGZImp.BasProject.DomainModels;
using System.Linq;
using DGZImp.Core.Utilities;
using System.Linq.Expressions;
using DGZImp.Core.Extensions;

using Microsoft.Extensions.DependencyInjection;
using Microsoft.AspNetCore.Http;
using DGZImp.BasProject.IRepositories;
using DGZImp.Core.Exceptions;
using DGZImp.WmsProject.Dtos;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json;
using DGZImp.Core.DbSqlSugar;
using System.Net;
using System.Xml.Linq;

namespace DGZImp.BasProject.Services
{
    public partial class Bas_LabelService
    {
        private readonly IHttpContextAccessor _httpContextAccessor;
        private readonly IBas_LabelRepository _repository;//访问数据库
        WebResponseContent webResponse = new WebResponseContent();

        [ActivatorUtilitiesConstructor]
        public Bas_LabelService(
            IBas_LabelRepository dbRepository,
            IHttpContextAccessor httpContextAccessor
            )
        : base(dbRepository)
        {
            _httpContextAccessor = httpContextAccessor;
            _repository = dbRepository;
            //多租户会用到这init代码，其他情况可以不用
            //base.Init(dbRepository);
        }


        /// <summary>
        /// 新建
        /// </summary>
        /// <param name="saveDataModel"></param>
        /// <returns></returns>
        public override WebResponseContent Add(SaveModel saveDataModel)
        {
            // 在保存数据库前的操作，所有数据都验证通过了，这一步执行完就执行数据库保存
            AddOnExecuting = (Bas_Label order, object list) =>
            {
                var test = order;
                var exist = _repository.Exists(x => x.LabelType == order.LabelType && x.IsValid == 1);
                if (exist) return webResponse.Error("已经存在相同标签类型的模板");

                return webResponse.OK();
            };


            return base.Add(saveDataModel);
        }



        public async Task<int> UpdateContent(ReqUpdateContent model)
        {
            var id = await _repository.DbContext.DoUpdateAsync<Bas_Label>(new
            {
                LabelId = model.LabelId,
                Content = model.Content,
                Size = model.Size,
                Zpl = model.Zpl
            }, t => t.LabelId == model.LabelId);
            return id;
        }

        public async Task<string> ModifyLabelDesign(ReqModifyLabelDesign data)
        {

            //var data = JsonConvert.DeserializeObject<ReqModifyLabelDesign>(model);
            // if (data.DetailList.Count <= 0) throw new AppException("数据视图及其字段必须维护");
            if (data.LabelId.IsNullOrEmpty()) throw new AppException("标签模板id必须存在");
            var fileId = data.LabelId;

            var exist = _repository.Exists(x => x.LabelType == data.LabelType && x.IsValid == 1 && x.LabelId != data.LabelId);

            if (exist) throw new AppException("已经存在其它相同标签类型的模板");
            _repository.SqlSugarClient.Ado.BeginTran();
            try
            {
                await _repository.DbContext.DoUpdateAsync<Bas_Label>(new { LabelName = data.LabelName, WidthSize = data.WidthSize, HeightSize = data.HeightSize, LabelType = data.LabelType, Remarks = data.Remarks, DocumentType = data.DocumentType, IsCommon = data.IsCommon }, t => t.LabelId == data.LabelId);


                if (data.DetailList.Count > 0)
                {



                    var detailList = await _repository.DbContext.Queryable<Bas_LabelConfigDetail>()
                    .Where(a => a.IsValid == 1)
                    .Where(a => a.LabelId == data.LabelId)
                    .ToListAsync();
                    var deleteList = new List<long>() { };

                    detailList.ForEach(v =>
                    {
                        if (data.DetailList.Where(a => a.LabelConfigDetailId == v.LabelConfigDetailId).FirstOrDefault() == null)
                            deleteList.Add(v.LabelConfigDetailId);
                    });

                    await _repository.DbContext.DoDeleteAsync<Bas_LabelConfigDetail>(a => deleteList.Contains(a.LabelConfigDetailId), true);

                    var insertDatas = new List<Bas_LabelConfigDetail> { };
                    var updateDatas = new List<Bas_LabelConfigDetail> { };
                    foreach (var item in data.DetailList)
                    {
                        if (string.IsNullOrEmpty(item.LabelConfigDetailName) || string.IsNullOrEmpty(item.LabelConfigDetailValue)) throw new AppException("标签字段内配置的信息必须填写");
                        item.LabelId = data.LabelId;
                        if (item.LabelConfigDetailId == 0) { await _repository.DbContext.DoInsertAsync(item); }
                        else
                        {
                            await _repository.DbContext.DoUpdateAsync<Bas_LabelConfigDetail>(item);
                        }
                    };

                }



                _repository.SqlSugarClient.Ado.CommitTran();
                return "";
            }
            catch (Exception e)
            {
                _repository.SqlSugarClient.Ado.RollbackTran();
                throw new AppException(e.Message);
            }

        }
        public async Task<List<Bas_LabelConfigDetail>> GetLabelConfigDetail(long? LabelId)
        {
            var list = await Db.Set<Bas_LabelConfigDetail>()
                  .Where(a => a.LabelId == LabelId)
                  .ToListAsync();
            return list;
        }
        public async Task<Bas_Label> Getbyid(long? vId, int type = 0)
        {
            var data = await Db.Set<Bas_Label>()
             .Where(a => a.LabelId == vId)
             .FirstAsync();


            return data;
        }
        public List<string> GetViewField(string viewName)
        {
            var lst = new List<string>() { };
            var viewFields = _repository.DbContext.DbMaintenance.GetColumnInfosByTableName(viewName, false);

            lst = viewFields.Select(a => a.DbColumnName).ToList();

            return lst;
        }


        public async Task<ResGetLabelData> GetLabelData(ReqGetLabelData model)
        {

            var labelRule = await GetLabelRule(model);

            var list = await GenerateLabelData(new ReqGenerateLabelData { LabelId = labelRule.LabelId, ValueList = model.ValueList });
            string value = null;
            var formatList = new List<List<string>>();
            formatList.Add(list.field);
            formatList.AddRange(list.view_data.Values.ToList());
            var dataContent = "";
            if (labelRule.DocumentType == 1)
            {
                if (labelRule.Zpl.IsNullOrEmpty()) throw new AppException("标签档案为在线设计，但没有找到在线设计的指令，请先设计标签。");
                dataContent = await FormatZpl(formatList, labelRule);
            }
            else
            {
                foreach (var l in formatList)
                {
                    dataContent = dataContent + string.Join(",", l) + "\r\n";
                }
            }


            return new ResGetLabelData
            {
                ViewData = list.view_data,
                LabelQty = labelRule.LabelQty,
                //temp_url = labelRule.file_path,
                TempName = labelRule.Name,
                SoftType = labelRule.DocumentType,
                DataContent = dataContent,
                Field = string.Join(",", list.field),
                Zpl = labelRule.Zpl
            };
        }

        public async Task<GetLabelDataClass> GetLabelRule(ReqGetLabelData model)
        {
            if (model.IsCommon == null) throw new AppException("查找标签模板:是否通用不能为空");
            var res = new List<GetLabelDataClass>() { };
            if (model.IsCommon == 0)
            {
                //非通用的情况
                /* if (model.label_type == null || string.IsNullOrEmpty(model.group_id) || string.IsNullOrEmpty(model.cust_id)
                     || string.IsNullOrEmpty(model.key_part_id))
                     throw new AppException("查找标签模板:工序,客户，物料,标签类型不能为空");
                 if (model.label_type == 3)
                 {
                     if (model.level.IsNullOrEmpty()) throw new AppException("查找标签模板:包装序号，层级不能为空。");
                 }

                 // 拉取当前工序下所有的模板
                 var groupTemplateList = await _db.Queryable<CLabelConfigT>()
                     .LeftJoin<CLabelT>((a, b) => a.label_id == b.id)
                     .LeftJoin<RFileT>((a, b, c) => b.file_id == c.id)
                     .Where((a, b, c) => a.group_id == model.group_id)
                     .Where((a, b, c) => b.label_type == model.label_type)
                     .WhereIF(model.label_type == 3, (a, b, c) => b.level == model.level)
                     .Where((a, b, c) => b.is_valid == "Y")
                     .Where((a, b, c) => a.is_valid == "Y")
                     .Select((a, b, c) => new GetLabelDataClass
                     {
                         cust_id = a.cust_id,
                         sku_id = a.sku_id,
                         label_qty = a.label_qty,
                         id = b.id,
                         name = b.name,
                         zpl = b.zpl,
                         file_path = c.file_path,
                         document_type = b.document_type
                     })
                     .ToListAsync();

                 //if (groupTemplateList.Count < 1) throw new AppException("当前工站未找到打印设定，请确认。");
                 //先确认当前客户是否存在特殊设置，若存在，
                 res = groupTemplateList.Where(a => a.cust_id == model.cust_id && a.sku_id == model.key_part_id).ToList();
                 if (res.Count < 1)
                     // cust_id=null + sku_id,判断物料是否存在通用设置
                     res = groupTemplateList.Where(a => a.sku_id == model.key_part_id && string.IsNullOrEmpty(a.cust_id)).ToList();
                 if (res.Count < 1)
                     // cust_id + sku_id=null,判断客户是否存在通用设置
                     res = groupTemplateList.Where(a => a.cust_id == model.cust_id && string.IsNullOrEmpty(a.sku_id)).ToList();
                 if (res.Count < 1)
                     //cust_id=null +sku_id=null,判断通用标签设置
                     res = groupTemplateList.Where(a => string.IsNullOrEmpty(a.cust_id) && string.IsNullOrEmpty(a.sku_id)).ToList();
                 //查找通用的标签
                 if (res.Count < 1)
                 {
                     //通用的情况
                     if (model.label_type == null) throw new AppException("查找标签模板:标签类型不能为空");
                     res = await _db.Queryable<CLabelT>()
                     .LeftJoin<RFileT>((a, b) => a.file_id == b.id)
                     .Where((a, b) => a.is_common == 1)
                     .Where((a, b) => a.label_type == model.label_type)
                     .WhereIF(model.label_type == 3, (a, b) => a.level == model.level)
                     .Where((a, b) => a.is_valid == "Y")
                     .Select((a, b) => new GetLabelDataClass
                     {
                         label_qty = 1,
                         id = a.id,
                         name = a.name,
                         zpl = a.zpl,
                         file_path = b.file_path,
                         document_type = a.document_type
                     })
                     .ToListAsync();
                 }*/
            }
            else
            {
                //通用的情况
                if (model.LabelType == null) throw new AppException("查找标签模板:标签类型不能为空");
                res = await _repository.DbContext.Queryable<Bas_Label>()
                .Where(a => a.IsCommon == 1)
                .Where(a => a.LabelType == model.LabelType)
                .WhereIF(model.LabelType == 3, a => a.Level == model.Level)
                .Where(a => a.IsValid == 1)
                .Select(a => new GetLabelDataClass
                {
                    LabelQty = 1,
                    LabelId = a.LabelId,
                    Name = a.LabelName,
                    Zpl = a.Zpl,
                    DocumentType = a.DocumentType
                })
                .ToListAsync();
            }

            if (res.Count > 1) throw new AppException("找到了多条打印设定，请检查");
            if (res.Count <= 0) throw new AppException("未找到打印设定。");

            return res[0];

        }


        public async Task<ResGenerateLabelData> GenerateLabelData(ReqGenerateLabelData model)
        {
            var label_id = model.LabelId;
            var filedstmp = new List<string>();
            var viewData = new Dictionary<string, List<string>>();
            //获取设置明细
            var list = await _repository.DbContext.Queryable<Bas_LabelConfigDetail>()
                .Where(t => t.LabelId == label_id && t.IsValid == 1)
                .ToListAsync();
            if (list.Count <= 0) throw new AppException("未设置打印标签字段");
            //逐一处理
            foreach (var a in list)
            {
                var factor = await _repository.DbContext.Queryable<Bas_BarcodeElement>()
                    .Where(t => t.CodingType == "View" && t.CodingParam == a.LabelConfigDetailName && t.IsValid == 1).FirstAsync();
                //获取视图数据
                if (factor.CodingFormula.IsNullOrEmpty())
                    throw new AppException(string.Format("要素设置异常，视图[{0}] 公式(KEY)不存在。请与系统管理员确认.", a.LabelConfigDetailName));

                var viewRowData = await this.GetViewData(a.LabelConfigDetailName, factor.CodingFormula, model.ValueList);

                var rows = new List<dynamic>(viewRowData);
                JObject row = JObject.FromObject(rows[0]);
                var fields = (a.LabelConfigDetailValue ?? "").Split(',').ToList();
                var nullFields = new List<string>() { };
                if (!a.AllowNullValue.IsNullOrEmpty())
                {
                    nullFields = a.AllowNullValue.Split(',').ToList();
                    fields.AddRange(nullFields);
                }
                filedstmp.AddRange(fields);
                foreach (var f in fields)
                {

                    if (string.IsNullOrEmpty(f)) continue;
                    if (!row.ContainsKey(f))
                        throw new AppException(string.Format("标签设置的视图变量[{0}]，在视图[{1}]信息中不存在，请与系统管理员确认.", f, a.LabelConfigDetailName));
                    if (((row[f] == null || row[f].ToString() == ""))
                        && !nullFields.Contains(f))
                        throw new AppException(string.Format("标签设置的视图变量[{0}]，在视图[{1}]信息中为空值，请与系统管理员确认.", f, a.LabelConfigDetailName));

                    var lstRes = new List<string>();
                    for (var i = 0; i < rows.Count; i++)
                    {

                        var tmpRow = JObject.FromObject(rows[i]);
                        var test = tmpRow[f];
                        var keyField = (string)(tmpRow[factor.CodingFormula]);
                        if (!viewData.ContainsKey(keyField)) viewData[keyField] = new List<string>() { };
                        viewData[keyField].Add(tmpRow[f].ToString());
                    }
                }
            }
            return new ResGenerateLabelData { field = filedstmp, view_data = viewData };
        }

        public async Task<dynamic> GetViewData(string viewName, string key, List<string> val, string col = null)
        {

            if (string.IsNullOrEmpty(viewName) || string.IsNullOrEmpty(key) || val.Count <= 0) throw new AppException("视图名称/主键/主键值 均不能为空");
            string strtmp = string.Join("','", val);
            string strIn = "('" + strtmp + "')";
            var result = await _repository.SqlSugarClient.Ado.SqlQueryAsync<dynamic>("select * from " + viewName + " where " + key + $" in  {strIn}");

            if (result.Count != val.Count) throw new Exception($"{viewName}视图数据查询的结果数量和要打印的标签数量不一致.");

            if (result.Count == 0) throw new AppException(string.Format("未查询到有效的视图[{0}]数据，栏位:{1},值:{2}", viewName, key, val));
            if (!string.IsNullOrEmpty(col) && !col.ToUpper().EndsWith("LIST"))
            {
                JObject jRes = JObject.FromObject(result[0]);
                return jRes[col];
            }
            return result.ToArray();
        }



        public async Task<string> FormatZpl(List<List<string>> list, GetLabelDataClass zpl)
        {
            string zplContent = null;
            string dataContent = null;
            var fields = list[0];
            list.RemoveAt(0);
            for (var i = 0; i < list.Count; i++)
            {
                zplContent = zpl.Zpl;
                var row = list[i];
                for (var j = 0; j < row.Count; j++)
                {
                    zplContent = zplContent.Replace("{" + fields[j] + "}", row[j]);
                }
                var end = zplContent.Substring(zplContent.Length - 3, 3);
                zplContent = zplContent.Substring(0, zplContent.Length - 3);
                zplContent = zplContent + "^PQ" + zpl.LabelQty + ",0," + zpl.LabelQty + ",N" + end;
                dataContent += zplContent;
                if (i != list.Count - 1)
                {
                    dataContent += "--||--";
                }
            }

            return dataContent;
        }

        public class GetLabelDataClass
        {
            public long LabelId { set; get; }
            public string Name { set; get; }
            //public string file_path { set; get; }
            public int? DocumentType { set; get; }
            public int? LabelQty { set; get; }

            public string AllowNullValue { set; get; }

            public string Zpl { set; get; }

            public string CustId { set; get; }

            public string SkuId { set; get; }


        }

    }
}
